10 BroadcastReceiver

一、基本概念

广播

  • 有序广播:被广播接收器接收后,可被终止,无法往下继续传达。
  • 普通广播:发送至每一个已经注册(订阅)的广播接收器,无法被终止。

广播接收器

  • 静态注册广播接收器:在AndroidManifest.xml中设置,程序不用启动亦可接收。
  • 动态注册广播接收器:代码中注册广播,程序未启动时,无法接收广播。

二、使用BroadcastReceiver

创建MyReceiver.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.xianxiaotao.learnreceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class MyReceiver extends BroadcastReceiver {
private static final String ARG = "data";
public MyReceiver() {}
@Override
public void onReceive(Context context, Intent intent) {
System.out.println("My Receiver : " + intent.getStringExtra(ARG));
}
/**
* 静态注册发送广播方式
*/
public static Intent newIntent(Context context, String args) {
Intent intent = new Intent(context, MyReceiver.class);
intent.putExtra(ARG, args);
return intent;
}
}

静态注册

1
2
3
4
5
6
7
8
9
<application>
...
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
</receiver>
</application>

发送广播

1
sendBroadcast(MyReceiver.newIntent(this, "xianxiaotao"));

三、动态注册和注销BroadcastReceiver

动态注册不需要在AndroidMainfest.xml文件中配置

删除AndroidMainfest.xml文件中对MyReceiver的声明

为MyReceiver增加动新的发送广播方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MyReceiver extends BroadcastReceiver {
private static final String ARG = "data";
public static final String ACTION = "MyReceiver.intent.action";
...
/**
* 动态注册发送广播方式
*/
public static Intent newIntent(String args) {
Intent intent = new Intent(MyReceiver.ACTION);
intent.putExtra(ARG, args);
return intent;
}
}

MainActivity中动态注册、发送广播和注销广播

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private MyReceiver mMyReceiver = null;
...
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnSendBroadcast: // 发送广播
sendBroadcast(MyReceiver.newIntent("xianxiaotao"));
break;
case R.id.btnRegBroadcast: // 注册广播
if (mMyReceiver == null) {
mMyReceiver = new MyReceiver();
registerReceiver(mMyReceiver, new IntentFilter(MyReceiver.ACTION));
}
break;
case R.id.btnUnregBroadcast: // 注销广播
if (mMyReceiver != null) {
unregisterReceiver(mMyReceiver);
mMyReceiver = null;
}
break;
}
}
}

实际开发中必须在onDestroy方法中注销广播,否则有内存泄漏的风险!!!

四、动态注册和静态注册的区别

  • 动态注册的广播会受Activity的生命周期的影响,当Activity销毁的时候,广播就失效了。
  • 而静态注册的广播,即使Activity销毁了,仍然可以收到广播。更牛掰的是即使杀死进程,仍然可以收到广播,关于这点不同的手机测试的结果是不同的。
  • 静态注册的广播,必需单独成一个类,不能像动态注册那样写在某个界面里。

在Android中,有一些action是不支持静态注册的:

  • android.intent.action.SCREEN_ON
  • android.intent.action.SCREEN_OFF
  • android.intent.action.BATTERY_CHANGED
  • android.intent.action.CONFIGURATION_CHANGED
  • android.intent.action.TIME_TICK

五、BroadcastReceiver的优先级

配置文件中可以设置优先级:android:priority=”10”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xianxiaotao.learnreceiver">
<application>
...
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="10">
<action android:name="com.xianxiaotao.learnreceiver.intent.action"/>
</intent-filter>
</receiver>
</application>
</manifest>

发送、终止/拦截有序广播

  • 发送有序广播必须使用sendOrderedBroadcast()方法。
  • 终止有序广播需要在onReceive()方法里使用abortBroadcast()。
  • 终止的是普通广播则会发生RuntimeException。

有序广播优先级规则

  • 优先级高的先接收(数字越大,优先级越高,其范围有待研究)
  • 同优先级的动静态广播接收器,动态优先于静态
  • 同优先级的动态广播接收器,或者同优先级的静态广播接收器,按照注册顺序。即静态:先扫描的大于后扫描的,动态:先注册的大于后注册的。

普通广播优先级规则

  • 无视优先级,动态广播接收器优先于静态广播接收器。
  • 按照注册顺序。静态:先扫描的大于后扫描的,动态:先注册的大于后注册的。